#include "precompiled.h"
#pragma hdrstop

namespace inf {
    const Color3	Color3::black		= Color3( 0.00f, 0.00f, 0.00f );
    const Color3	Color3::white		= Color3( 1.00f, 1.00f, 1.00f );
    const Color3	Color3::red		= Color3( 1.00f, 0.00f, 0.00f );
    const Color3	Color3::green		= Color3( 0.00f, 1.00f, 0.00f );
    const Color3	Color3::blue		= Color3( 0.00f, 0.00f, 1.00f );
    const Color3	Color3::yellow	= Color3( 1.00f, 1.00f, 0.00f );
    const Color3	Color3::magenta	= Color3( 1.00f, 0.00f, 1.00f );
    const Color3	Color3::cyan		= Color3( 0.00f, 1.00f, 1.00f );
    const Color3	Color3::orange	= Color3( 1.00f, 0.50f, 0.00f );
    const Color3	Color3::purple	= Color3( 0.60f, 0.00f, 0.60f );
    const Color3	Color3::pink		= Color3( 0.73f, 0.40f, 0.48f );
    const Color3	Color3::brown		= Color3( 0.40f, 0.35f, 0.08f );
    const Color3	Color3::ltGrey	= Color3( 0.75f, 0.75f, 0.75f );
    const Color3	Color3::mdGrey	= Color3( 0.50f, 0.50f, 0.50f );
    const Color3	Color3::dkGrey	= Color3( 0.25f, 0.25f, 0.25f );
    const Color3	Color3::ltBlue	= Color3( 0.40f, 0.70f, 1.00f );
    const Color3	Color3::dkRed		= Color3( 0.70f, 0.00f, 0.00f );

    /*
    =============
    Color3::to_string
    =============
    */
    const char* Color3::to_string( int precision ) const {
        return float_array_to_string_ANSI( to_float_ptr(), get_dimension(), precision );
    }

    /*
    =============
    lerp

    Linearly inperpolates one vector to another.
    =============
    */
    void Color3::lerp( const Color3& v1, const Color3& v2, const float l ) {
        if ( l <= 0.0f ) {
            (*this) = v1;
        } else if ( l >= 1.0f ) {
            (*this) = v2;
        } else {
            (*this) = v1 + l * ( v2 - v1 );
        }
    }

    const Color4	Color4::black		= Color4( 0.00f, 0.00f, 0.00f, 1.00f );
    const Color4	Color4::white		= Color4( 1.00f, 1.00f, 1.00f, 1.00f );
    const Color4	Color4::red		= Color4( 1.00f, 0.00f, 0.00f, 1.00f );
    const Color4	Color4::green		= Color4( 0.00f, 1.00f, 0.00f, 1.00f );
    const Color4	Color4::blue		= Color4( 0.00f, 0.00f, 1.00f, 1.00f );
    const Color4	Color4::yellow	= Color4( 1.00f, 1.00f, 0.00f, 1.00f );
    const Color4	Color4::magenta	= Color4( 1.00f, 0.00f, 1.00f, 1.00f );
    const Color4	Color4::cyan		= Color4( 0.00f, 1.00f, 1.00f, 1.00f );
    const Color4	Color4::orange	= Color4( 1.00f, 0.50f, 0.00f, 1.00f );
    const Color4	Color4::purple	= Color4( 0.60f, 0.00f, 0.60f, 1.00f );
    const Color4	Color4::pink		= Color4( 0.73f, 0.40f, 0.48f, 1.00f );
    const Color4	Color4::brown		= Color4( 0.40f, 0.35f, 0.08f, 1.00f );
    const Color4	Color4::ltGrey	= Color4( 0.75f, 0.75f, 0.75f, 1.00f );
    const Color4	Color4::mdGrey	= Color4( 0.50f, 0.50f, 0.50f, 1.00f );
    const Color4	Color4::dkGrey	= Color4( 0.25f, 0.25f, 0.25f, 1.00f );
    const Color4	Color4::ltBlue	= Color4( 0.40f, 0.70f, 1.00f, 1.00f );
    const Color4	Color4::dkRed		= Color4( 0.70f, 0.00f, 0.00f, 1.00f );

    /*
    =============
    Color4::to_string
    =============
    */
    const char* Color4::to_string( int precision ) const {
        return float_array_to_string_ANSI( to_float_ptr(), get_dimension(), precision );
    }

    /*
    =============
    lerp

    Linearly inperpolates one vector to another.
    =============
    */
    void Color4::lerp( const Color4& v1, const Color4& v2, const float l ) {
        if ( l <= 0.0f ) {
            (*this) = v1;
        } else if ( l >= 1.0f ) {
            (*this) = v2;
        } else {
            (*this) = v1 + l * ( v2 - v1 );
        }
    }

    /*
    ================
    ColorFloatToByte
    ================
    */
    INF_INLINE static byte ColorFloatToByte( float c ) {
        return math::ftob( c * 255.0f );
    }

    /*
    ================
    Color4::pack_Color
    ================
    */
    dword Color4::pack_Color( const Vec3& color, float alpha ) {
        dword dw, dx, dy, dz;

        dx = ColorFloatToByte( color.x );
        dy = ColorFloatToByte( color.y );
        dz = ColorFloatToByte( color.z );
        dw = ColorFloatToByte( alpha );

#if defined( _XENON )
        return ( dx << 24 ) | ( dy << 16 ) | ( dz << 8 ) | ( dw << 0 );
#elif defined( _WIN32 ) || defined( __linux__ )
        return ( dx << 0 ) | ( dy << 8 ) | ( dz << 16 ) | ( dw << 24 );
#elif defined( MACOS_X )
#if defined( __ppc__ )
        return ( dx << 24 ) | ( dy << 16 ) | ( dz << 8 ) | ( dw << 0 );
#else
        return ( dx << 0 ) | ( dy << 8 ) | ( dz << 16 ) | ( dw << 24 );
#endif
#else
//#error OS define is required!
#endif
    }

    /*
    ================
    Color4::pack_Color
    ================
    */
    dword Color4::pack_Color( const Vec4& color ) {
        dword dw, dx, dy, dz;

        dx = ColorFloatToByte( color.x );
        dy = ColorFloatToByte( color.y );
        dz = ColorFloatToByte( color.z );
        dw = ColorFloatToByte( color.w );

#if defined( _XENON )
        return ( dx << 24 ) | ( dy << 16 ) | ( dz << 8 ) | ( dw << 0 );
#elif defined( _WIN32 ) || defined( __linux__ )
        return ( dx << 0 ) | ( dy << 8 ) | ( dz << 16 ) | ( dw << 24 );
#elif defined( MACOS_X )
#if defined( __ppc__ )
        return ( dx << 24 ) | ( dy << 16 ) | ( dz << 8 ) | ( dw << 0 );
#else
        return ( dx << 0 ) | ( dy << 8 ) | ( dz << 16 ) | ( dw << 24 );
#endif
#else
//#error OS define is required!
#endif
    }

    /*
    ================
    Color4::unpack_Color
    ================
    */
    void Color4::unpack_Color( const dword color, Vec4& unpackedColor ) {
#if defined( _XENON )
        unpackedColor.set( ( ( color >> 24 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 16 ) & 255 ) * ( 1.0f / 255.0f ), 
            ( ( color >> 8 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 0 ) & 255 ) * ( 1.0f / 255.0f ) );
#elif defined( _WIN32 ) || defined( __linux__ )
        unpackedColor.set( ( ( color >> 0 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 8 ) & 255 ) * ( 1.0f / 255.0f ), 
            ( ( color >> 16 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 24 ) & 255 ) * ( 1.0f / 255.0f ) );
#elif defined(MACOS_X)
#if defined ( __ppc__ )
        unpackedColor.set( ( ( color >> 24 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 16 ) & 255 ) * ( 1.0f / 255.0f ), 
            ( ( color >> 8 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 0 ) & 255 ) * ( 1.0f / 255.0f ) );
#else
        unpackedColor.set( ( ( color >> 0 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 8 ) & 255 ) * ( 1.0f / 255.0f ), 
            ( ( color >> 16 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 24 ) & 255 ) * ( 1.0f / 255.0f ) );
#endif
#else
///#error OS define is required!
#endif
    }

    /*
    ================
    Color3::pack_Color
    ================
    */
    dword Color3::pack_Color( const Vec3& color ) {
        dword dx, dy, dz;

        dx = ColorFloatToByte( color.x );
        dy = ColorFloatToByte( color.y );
        dz = ColorFloatToByte( color.z );

#if defined(_WIN32) || defined(__linux__)
        return ( dx << 0 ) | ( dy << 8 ) | ( dz << 16 );
#elif defined(MACOS_X)
#if defined(__ppc__)
        return ( dy << 16 ) | ( dz << 8 ) | ( dx << 0 );
#else
        return ( dx << 0 ) | ( dy << 8 ) | ( dz << 16 );
#endif
//#else
//#error OS define is required!
#endif
    }

    /*
    ================
    Color3::unpack_Color
    ================
    */
    void Color3::unpack_Color( const dword color, Vec3& unpackedColor ) {
#if defined(_WIN32) || defined(__linux__)
        unpackedColor.set( ( ( color >> 0 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 8 ) & 255 ) * ( 1.0f / 255.0f ), 
            ( ( color >> 16 ) & 255 ) * ( 1.0f / 255.0f ) );
#elif defined(MACOS_X)
#if defined(__ppc__)
        unpackedColor.set( ( ( color >> 16 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 8 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 0 ) & 255 ) * ( 1.0f / 255.0f ) );
#else
        unpackedColor.set( ( ( color >> 0 ) & 255 ) * ( 1.0f / 255.0f ),
            ( ( color >> 8 ) & 255 ) * ( 1.0f / 255.0f ), 
            ( ( color >> 16 ) & 255 ) * ( 1.0f / 255.0f ) );
#endif
#else
//#error OS define is required!
#endif
    }


}   // ::inf
